package game.block.trap;

import game.block.Locator;
import game.block.command.Command;
import game.block.command.WindCommand;
import game.block.entity.MovableEntity;
import game.block.entity.TrapEntity;
import game.block.game.Board;
import game.block.tile.Tile;
import game.block.turn.Turn;

import java.util.ArrayList;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.ParticleEffect;
import com.badlogic.gdx.graphics.g2d.ParticleEmitter;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;

public class Wind extends TrapEntity {

    private ParticleEffect particles;
    private OrthographicCamera camera;
    private Vector3 windPos;
    private Tile secondTile;
    private Vector2 adj;
    private int direction;
    private boolean tileOccupied;
    private Board board;

    public Wind(Vector2 pos, Tile tile, char dir, OrthographicCamera camera, Board board) {
        super(pos, tile, null, TRAPTYPE.WIND);
        this.camera = camera;
        this.board = board;
        tileOccupied = false;
        particles = new ParticleEffect();
        particles.load(Gdx.files.internal("data/wind"), Gdx.files.internal("data/art/"));
        adj = new Vector2(0, 0);
        Locator.getEffects().add(particles);
        ParticleEmitter emitter = Locator.getEffects().get(Locator.getEffects().size() - 1).getEmitters().get(0);
        switch (dir) {
        case 'r':
            direction = 0;
            emitter.getAngle().setLow(0);
            emitter.getAngle().setHigh(-45,45);
            adj.set(TILE_SIZE / 8, TILE_SIZE / 2);
            break;
        case 'u':
            direction = 90;
            emitter.getAngle().setLow(90);
            adj.set(TILE_SIZE / 2, TILE_SIZE / 8);
            break;
        case 'd':
            direction = -90;
            emitter.getAngle().setLow(-90);
            emitter.getAngle().setHigh(-45, -135);
            adj.set(TILE_SIZE / 2, TILE_SIZE - TILE_SIZE / 8);
            break;
        case 'l':
            direction = 180;
            emitter.getAngle().setLow(-180);
            emitter.getAngle().setHigh(-215,-135);
            adj.set(TILE_SIZE - TILE_SIZE / 8, TILE_SIZE / 2);
            break;

        }
        windPos = new Vector3(tile.getPosition().x + adj.x, tile.getPosition().y + adj.y, 0);
        camera.project(windPos);
        particles.setPosition(windPos.x, windPos.y);
        particles.start();
    }

    public void initSecondTile(ArrayList<Tile> tileList, Board board) {
        int cPos = (int) (currentTile.getPosition().x / TILE_SIZE);
        int rPos = (int) (currentTile.getPosition().y / TILE_SIZE);
        int arrayPos = (board.getCols() - 1 - rPos) * board.getRows() + cPos;
        switch (direction) {
        case 0: // right
            secondTile = tileList.get(arrayPos + 1);
            break;
        case 90: // up
            secondTile = tileList.get(arrayPos - board.getRows());
            break;
        case -90: // down
            secondTile = tileList.get(arrayPos + board.getRows());
            break;
        case 180: // left
            secondTile = tileList.get(arrayPos - 1);
            break;
        }
        secondTile.add(this);
        secondTile.setSprite(new Sprite(new Texture(Gdx.files.internal(NORMAL_TILE))));
    }

    @Override
    public void update(float delta) {
        super.update(delta);
        windPos = new Vector3(currentTile.getPosition().x + adj.x, currentTile.getPosition().y + adj.y, 0);
        camera.project(windPos);
        particles.setPosition(windPos.x, windPos.y);
        if (Locator.getEffects().size() > 0) {
            ParticleEmitter emitter = Locator.getEffects().get(Locator.getEffects().size() - 1).getEmitters().get(0);
            emitter.getScale().setHigh(1 / camera.zoom * 32);
        }

        if (!tileOccupied && currentTile.containsStone()) {
            Locator.getEffects().remove(particles);
            tileOccupied = true;
        } else if (tileOccupied && !currentTile.containsStone()) {
            Locator.getEffects().add(particles);
            tileOccupied = false;
        }

        /*if (secondTile.containsStone()) {
            ParticleEmitter emitter = Locator.getEffects().get(Locator.getEffects().size() - 1).getEmitters().get(0);
            emitter.getLife().setHigh(emitter.getLife().getHighMin() / 2);
        }*/
    }

    @Override
    public Command advance() {
        return null;
    }

    @Override
    public void applyEffect(MovableEntity block, Board gameBoard, Turn currentTurn, Tile tileMovedTo) {
        if (!currentTile.containsStone() && !block.counterEffect(this)) {
            Turn turn=new Turn();
            Locator.getAudio().playSound(SOUND.WIND.getValue());
            if (tileMovedTo.equals(currentTile)) {
                Tile next = determineVelocity(block, board, currentTile);
                if (next != null) {
                    turn.addCommand(new WindCommand(block, currentTile, next, board, turn));
                    gameBoard.getQueuedTurns().add(turn);
                }
            } else {
                Tile next = determineVelocity(block, board, secondTile);
                if (next != null) {
                    turn.addCommand(new WindCommand(block, secondTile, next, board, turn));
                    gameBoard.getQueuedTurns().add(turn);
                }
            }
        }
    }

    public Tile determineVelocity(MovableEntity block, Board board, Tile currentTile) {
        int cPos = (int) (currentTile.getPosition().x / TILE_SIZE);
        int rPos = (int) (currentTile.getPosition().y / TILE_SIZE);
        int arrayPos = (board.getCols() - 1 - rPos) * board.getRows() + cPos;

        if (direction == 0) { // moving right
            if (arrayPos % board.getRows() != board.getRows() - 1) {
                Tile tile = board.getTiles().get(arrayPos + 1);
                if (block.getCurrentTile()==tile || (!tile.containsBlock() && !tile.containsWall())) {
                    return tile;
                }
            }
        } else if (direction == 180) { // moving left
            if (arrayPos % board.getRows() != 0) {
                Tile tile = board.getTiles().get(arrayPos - 1);
                if (block.getCurrentTile()==tile || (!tile.containsBlock() && !tile.containsWall())) {
                    return tile;
                }
            }
        } else if (direction == 90) { // moving up
            if (arrayPos - board.getRows() > 0) {
                Tile tile = board.getTiles().get(arrayPos - board.getRows());
                if (block.getCurrentTile()==tile || (!tile.containsBlock() && !tile.containsWall())) {
                    return tile;
                }
            }
        } else if (direction == -90) { // moving down
            if (arrayPos + board.getRows() < board.getTiles().size()) {
                Tile tile = board.getTiles().get(arrayPos + board.getRows());
                if (block.getCurrentTile()==tile || (!tile.containsBlock() && !tile.containsWall())) {
                    return tile;
                }
            }
        }
        return null;
    }

    @Override
    public Command retract() {
        return null;
    }

    @Override
    public void setInfo() {
        info = "Name:  Wind Trap\nFunction:  Pushes blocks the direction it's blowing";
    }
}